﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SD.Entities;
using SD.DAL;
using SD.IDAL;
using SD.IBUS;

namespace SD.BUS
{
    public class OrganizationBIZ : BaseBIZ, IOrganizationBIZ
    {
        IOrganizationDAO orgDAO;

        public OrganizationBIZ()
        {
            this.orgDAO = new OrganizationDAO();
        }

        #region IOrganizationBIZ Members

        /// <summary>
        /// List organizations' information
        /// </summary>
        /// <param name="includeInactive">Indicate whether inactive organization will be included in the return list</param>
        /// <returns>Table contains information of organizations</returns>
        public DataTable ListOrganization(Boolean includeInactive)
        {
            DataTable dtbResult = new DataTable();
            dtbResult.Columns.Add("OrgId");
            dtbResult.Columns.Add("Name");
            dtbResult.Columns.Add("Line1");
            dtbResult.Columns.Add("Postcode");
            dtbResult.Columns.Add("Contact");
            dtbResult.Columns.Add("IsActive");

            try
            {
                List<Organization> lstOrg = GetAll(includeInactive);
                if (lstOrg.Count > 0)
                {
                    foreach (Organization org in lstOrg)
                    {
                        dtbResult.Rows.Add(org.OrgId, org.Name, 
                                            org.Address != null ? org.Address.Line1 : "N/A",
                                            org.Address != null ? org.Address.PostCode : "N/A",
                                            org.Contact != null ? org.Contact.FirstName : "N/A", 
                                            org.IsActive);
                    }
                }
            }
            catch (SqlException ex)
            {
                throw ex;
            }

            return dtbResult;
        }

        /// <summary>
        /// Filter organization list base on a filter expression
        /// </summary>
        /// <param name="filterExpression">filter expression</param>
        /// <param name="includeInactive">Indicate whether inactive organization will be included in the return list</param>
        /// <returns>List of filtered organization</returns>
        public DataTable ListFilteredOrganization(String filterExpression, Boolean includeInactive)
        {
            DataTable dtbResult = new DataTable();
            dtbResult.Columns.Add("OrgId");
            dtbResult.Columns.Add("Name");
            dtbResult.Columns.Add("Line1");
            dtbResult.Columns.Add("Postcode");
            dtbResult.Columns.Add("Contact");
            dtbResult.Columns.Add("IsActive");

            try
            {                
                List<Organization> lstOrg = orgDAO.GetByFilter(filterExpression, includeInactive);

                if (lstOrg.Count > 0)
                {
                    foreach (Organization org in lstOrg)
                    {
                        dtbResult.Rows.Add(org.OrgId, org.Name,
                                            org.Address != null ? org.Address.Line1 : "N/A",
                                            org.Address != null ? org.Address.PostCode : "N/A",
                                            org.Contact != null ? org.Contact.FirstName : "N/A",
                                            org.IsActive);
                    }
                }
            }
            catch (SqlException ex)
            {
                throw ex;
            }

            return dtbResult;
        }

        /// <summary>
        /// Get all organizations stored in the database
        /// </summary>
        /// <returns>List of existing organization</returns>
        public List<Organization> GetAll(Boolean includeInactive)
        {
            List<Organization> result = new List<Organization>();

            try
            {
                result = orgDAO.GetAll(includeInactive);
            }
            catch (SqlException ex)
            {
                throw ex;
            }

            return result;
        }

        /// <summary>
        /// Get organization by its ID
        /// </summary>
        /// <param name="orgId">The ID used to find the organization</param>
        /// <returns>Organization has the same ID with the inputed param</returns>
        public Organization GetById(string orgId)
        {
            Organization result = null;

            try
            {
                result = orgDAO.GetById(orgId);
            }
            catch (SqlException ex)
            {
                throw ex;
            }

            return result;
        }

        /// <summary>
        /// Add new organization to database
        /// </summary>
        /// <param name="org">The new organization will be added</param>
        public void Insert(Organization org)
        {
            try
            {
                // insert organization
                orgDAO.Insert(org);

                // insert detail 2
                IOrgDetail2DAO orgDetail2DAO = new OrgDetail2DAO();
                foreach (ReferenceData refData in org.Details2)
                {
                    orgDetail2DAO.Insert(org.OrgId, refData.RefId);
                }

                // insert programes
                if (org.Programmes != null) // user select programme for new org
                {
                    IOrgProgrammeDAO orgProgrameDAO = new OrgProgrammeDAO();
                    foreach (Programme programme in org.Programmes)
                    {
                        orgProgrameDAO.Insert(org.OrgId, programme.ProgrammeId);
                    }
                }

                // insert services
                if (org.Services != null) // user select programme for new org
                {
                    IOrgServiceDAO orgServiceDAO = new OrgServiceDAO();
                    foreach (Service service in org.Services)
                    {
                        orgServiceDAO.Insert(org.OrgId, service.ServiceId);
                    }
                }
            }
            catch (SqlException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Update an existing organization
        /// </summary>
        /// <param name="org">The organization will be updated</param>
        public void Update(Organization org)
        {
            try
            {
                // update detail 1
                orgDAO.Update(org);                              
                
                // update detail 2
                IOrgDetail2DAO detail2DAO = new OrgDetail2DAO();
                detail2DAO.Update(org.OrgId, org.Details2);

                // update detail 3


                // update detail 4 - premise
                IPremiseDAO premiseDAO = new PremiseDAO();

                List<Service> lstServices = org.Services;
                foreach (Service service in lstServices)
                {
                    List<Premise> lstPremise = service.Premises;
                    foreach (Premise premise in lstPremise)
                    {
                        premiseDAO.Update(premise);
                    }
                }

                // update detail 5 - Supporting material
                ISupportingMaterialDAO smDAO = new SupportingMaterialDAO();
                foreach (SupportingMaterial sm in org.SupportingMaterials)
                {
                    smDAO.Update(sm);
                }

            }
            catch (SqlException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Delete an address
        /// </summary>
        /// <param name="orgId">The ID indicates organization will be deleted.</param>
        public void Delete(string orgId)
        {
            try
            {
                orgDAO.Delete(orgId);
            }
            catch (SqlException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Set active status of an goranization
        /// </summary>
        /// <param name="orgId">ID of the organization</param>
        /// <param name="status">New active status of the organization</param>
        public void SetActive(string orgId, bool status)
        {
            try
            {
                orgDAO.SetActive(orgId,status);                
            }
            catch (SqlException ex)
            {                
                throw ex;
            }
        
        }

        /// <summary>
        /// Get Organization by name
        /// </summary>
        /// <param name="orgname">orgname parameter</param>
        /// <returns>Return list of organization</returns>
        public List<Organization> GetOrgByName(string orgname)
        {
            List<Organization> result = new List<Organization>();

            try
            {
                result = orgDAO.GetOrgByName(orgname);
            }
            catch (SqlException ex)
            {
                throw ex;
            }

            return result;
        }

        #endregion
    }
}
